package org.rsbot.script.methods;

import org.rsbot.script.wrappers.*;

import java.awt.*;

/**
 * Bank related operations.
 */
public class Bank extends MethodProvider {
    public static final int[] BANKERS = new int[]{44, 45, 494, 495, 496, 497,
            498, 499, 553, 909, 958, 1036, 2271, 2354, 2355, 2718, 2759, 3198,
            3293, 3416, 3418, 3824, 4456, 4457, 4458, 4459, 5488, 5901, 5912,
            6362, 6532, 6533, 6534, 6535, 7605, 8948, 9710, 14367};
    public static final int[] BANK_BOOTHS = new int[]{782, 2213, 2995, 5276,
            6084, 10517, 11402, 11758, 12759, 14367, 19230, 20325, 24914, 11338,
            25808, 26972, 29085, 52589, 34752, 35647, 36786, 2012, 2015, 2019,
            42217, 42377, 42378};
    public static final int[] BANK_CHESTS = new int[]{2693, 4483, 8981, 12308, 21301, 20607,
            21301, 27663, 42192};
    public static final int[] DEPOSIT_BOXES = {2045, 9398, 20228, 24995, 25937,
            26969, 32924, 32930, 32931, 34755, 36788, 39830, 45079};
    public static final int[] DO_NOT_DEPOSIT = new int[]{1265, 1267, 1269,
            1273, 1271, 1275, 1351, 590, 303};


    public static final int INTERFACE_BANK = 762;
    public static final int INTERFACE_BANK_BUTTON_CLOSE = 43;
    public static final int INTERFACE_BANK_BUTTON_DEPOSIT_BEAST_INVENTORY = 38;
    public static final int INTERFACE_BANK_BUTTON_DEPOSIT_CARRIED_ITEMS = 34;
    public static final int INTERFACE_BANK_BUTTON_DEPOSIT_WORN_ITEMS = 36;
    public static final int INTERFACE_BANK_BUTTON_HELP = 44;
    public static final int INTERFACE_BANK_BUTTON_INSERT = 15;
    public static final int INTERFACE_BANK_BUTTON_ITEM = 19;
    public static final int INTERFACE_BANK_BUTTON_NOTE = 19;
    public static final int INTERFACE_BANK_BUTTON_SEARCH = 17;
    public static final int INTERFACE_BANK_BUTTON_SWAP = 15;
    public static final int INTERFACE_BANK_BUTTON_OPEN_EQUIP = 117;
    public static final int INTERFACE_BANK_INVENTORY = 93;
    public static final int INTERFACE_BANK_ITEM_FREE_COUNT = 29;
    public static final int INTERFACE_BANK_ITEM_FREE_MAX = 30;
    public static final int INTERFACE_BANK_ITEM_MEMBERS_COUNT = 31;
    public static final int INTERFACE_BANK_ITEM_MEMBERS_MAX = 32;
    public static final int INTERFACE_BANK_SCROLLBAR = 114;
    public static final int INTERFACE_BANK_SEARCH = 752;
    public static final int INTERFACE_BANK_SEARCH_INPUT = 5;

    public static final int INTERFACE_EQUIPMENT = 667;
    public static final int INTERFACE_EQUIPMENT_COMPONENT = 7;

    public static final int INTERFACE_COLLECTION_BOX = 109;
    public static final int INTERFACE_COLLECTION_BOX_CLOSE = 14;

    public static final int[] INTERFACE_BANK_TAB = {63, 61, 59, 57, 55, 53, 51, 49, 47};
    public static final int[] INTERFACE_BANK_TAB_FIRST_ITEM = {78, 79, 80, 81, 82, 83, 84, 85, 86};

    public static final int INTERFACE_DEPOSIT_BOX = 11;
    public static final int INTERFACE_DEPOSIT_BOX_BUTTON_CLOSE = 15;
    public static final int INTERFACE_DEPOSIT_BUTTON_DEPOSIT_BEAST_INVENTORY = 23;
    public static final int INTERFACE_DEPOSIT_BUTTON_DEPOSIT_CARRIED_ITEMS = 19;
    public static final int INTERFACE_DEPOSIT_BUTTON_DEPOSIT_WORN_ITEMS = 21;


    Bank(final MethodContext ctx) {
        super(ctx);
    }

    /**
     * Closes the bank interface. Supports deposit boxes.
     *
     * @return <tt>true</tt> if the bank interface is no longer open.
     */
    public boolean close() {
        if (isOpen()) {
            if (methods.interfaces.getComponent(INTERFACE_BANK, INTERFACE_BANK_BUTTON_CLOSE).doClick()) {
                for (int i = 0; i < 4 && isOpen(); i++) {
                    sleep(random(125, 150));
                }
            }
            return !isOpen();
        } else if (isDepositOpen()) {
            if (methods.interfaces.getComponent(INTERFACE_DEPOSIT_BOX, INTERFACE_DEPOSIT_BOX_BUTTON_CLOSE).doClick()) {
                for (int i = 0; i < 4 && isDepositOpen(); i++) {
                    sleep(random(125, 150));
                }
            }
            return !isDepositOpen();
        }
        return true;
    }

    /**
     * If bank is open, deposits specified amount of an item into the bank.
     * Supports deposit boxes.
     *
     * @param itemID The ID of the item.
     * @param number The amount to deposit. 0 deposits All. 1,5,10 deposit
     *               corresponding amount while other numbers deposit X.
     * @return <tt>true</tt> if successful; otherwise <tt>false</tt>.
     */
    public boolean deposit(final int itemID, final int number) {
        if (isOpen() || isDepositOpen()) {
            if (number < 0) {
                throw new IllegalArgumentException("number < 0 (" + number + ")");
            }
            RSComponent item = null;
            int itemCount = 0;
            final int invCount = isOpen() ? methods.inventory.getCount(true) : getBoxCount();
            if (!isOpen()) {
                boolean match = false;
                for (int i = 0; i < 28; i++) {
                    final RSComponent comp = methods.interfaces.get(11).getComponent(17).getComponent(i);
                    if (comp.getComponentID() == itemID) {
                        itemCount += comp.getComponentStackSize();
                        if (!match) {
                            item = comp;
                            match = true;
                        }
                    }
                    if (itemCount > 1) {
                        break;
                    }
                }
            } else {
                item = methods.inventory.getItem(itemID).getComponent();
                itemCount = methods.inventory.getCount(true, itemID);
            }
            if (item == null) {
                return true;
            }
            switch (number) {
                case 0:
                    item.interact(itemCount > 1 ? "Deposit-All" : "Deposit");
                    break;
                case 1:
                    item.interact("Deposit");
                    break;
                case 5:
                    item.interact("Deposit-" + number);
                    break;
                default:
                    if (!item.interact("Deposit-" + number)) {
                        if (item.interact("Deposit-X")) {
                            sleep(random(1000, 1300));
                            methods.inputManager.sendKeys(String.valueOf(number), true);
                        }
                    }
                    break;
            }
            sleep(300);
            final int cInvCount = isOpen() ? methods.inventory.getCount(true) : getBoxCount();
            return cInvCount < invCount || cInvCount == 0;
        }
        return false;
    }

    /**
     * If bank is open, deposits specified amount of an item into the bank.
     * Supports deposit boxes.
     *
     * @param itemName The Name of the item.
     * @param number   The amount to deposit. 0 deposits All. 1,5,10 deposit
     *                 corresponding amount while other numbers deposit X.
     * @return <tt>true</tt> if successful; otherwise <tt>false</tt>.
     */
    public boolean deposit(final String itemName, final int number) {
        return deposit(methods.inventory.getItemID(itemName), number);
    }

    /**
     * Deposits all items in methods.inventory. Supports deposit boxes.
     *
     * @return <tt>true</tt> on success.
     */
    public boolean depositAll() {
        return isOpen() ? methods.interfaces.getComponent(INTERFACE_BANK, INTERFACE_BANK_BUTTON_DEPOSIT_CARRIED_ITEMS).doClick()
                : isDepositOpen() && methods.interfaces.getComponent(INTERFACE_DEPOSIT_BOX, INTERFACE_DEPOSIT_BUTTON_DEPOSIT_CARRIED_ITEMS).doClick();
    }

    /**
     * Deposits all items in inventory except for the given IDs. Supports
     * deposit boxes.
     *
     * @param items The items not to deposit.
     * @return true on success.
     */
    public boolean depositAllExcept(final int... items) {
        if (isOpen() || isDepositOpen()) {
            boolean deposit = true;
            int invCount = isOpen() ? methods.inventory.getCount(true) : getBoxCount();
            outer:
            for (int i = 0; i < 28; i++) {
                final RSComponent item = isOpen() ? methods.inventory.getItemAt(i).getComponent() : methods.interfaces.get(11).getComponent(17).getComponent(i);
                if (item != null && item.getComponentID() != -1) {
                    for (final int id : items) {
                        if (item.getComponentID() == id) {
                            continue outer;
                        }
                    }
                    for (int tries = 0; tries < 5; tries++) {
                        deposit(item.getComponentID(), 0);
                        sleep(random(600, 900));
                        final int cInvCount = isOpen() ? methods.inventory.getCount(true) : getBoxCount();
                        if (cInvCount < invCount) {
                            invCount = cInvCount;
                            continue outer;
                        }
                    }
                    deposit = false;
                }
            }
            return deposit;
        }
        return false;
    }

    /**
     * Deposit everything your player has equipped. Supports deposit boxes.
     *
     * @return <tt>true</tt> on success.
     * @since 6 March 2009.
     */
    public boolean depositAllEquipped() {
        if (isOpen()) {
            return methods.interfaces.getComponent(INTERFACE_BANK, INTERFACE_BANK_BUTTON_DEPOSIT_WORN_ITEMS).doClick();
        }
        return isDepositOpen() && methods.interfaces.getComponent(INTERFACE_DEPOSIT_BOX, INTERFACE_DEPOSIT_BUTTON_DEPOSIT_WORN_ITEMS).doClick();
    }

    /**
     * Deposits everything your familiar is carrying. Supports deposit boxes.
     *
     * @return <tt>true</tt> on success
     * @since 6 March 2009.
     */
    public boolean depositAllFamiliar() {
        if (isOpen()) {
            return methods.interfaces.getComponent(INTERFACE_BANK, INTERFACE_BANK_BUTTON_DEPOSIT_BEAST_INVENTORY).doClick();
        }
        return isDepositOpen() && methods.interfaces.getComponent(INTERFACE_DEPOSIT_BOX, INTERFACE_DEPOSIT_BUTTON_DEPOSIT_BEAST_INVENTORY).doClick();
    }

    /**
     * Returns the sum of the count of the given items in the bank.
     *
     * @param items The array of items.
     * @return The sum of the stacks of the items.
     */
    public int getCount(final int... items) {
        int itemCount = 0;
        final RSItem[] inventoryArray = getItems();
        for (final RSItem item : inventoryArray) {
            for (final int id : items) {
                if (item.getID() == id) {
                    itemCount += item.getStackSize();
                }
            }
        }
        return itemCount;
    }

    /**
     * Get current tab open in the bank.
     *
     * @return int of tab (0-8), or -1 if none are selected (bank is not open).
     */
    public int getCurrentTab() {
        /*for (int i = 0; i < INTERFACE_BANK_TAB.length; i++) {
              if (methods.interfaces.get(INTERFACE_BANK).getComponent(INTERFACE_BANK_TAB[i] - 1).getBackgroundColor() == 1419) {
                  return i;
              }
          }
          return -1;*/
        return ((methods.settings.getSetting(1248) >>> 24) - 136) / 8;
    }

    /**
     * Gets the bank interface.
     *
     * @return The bank <code>RSInterface</code>.
     */
    public RSInterface getInterface() {
        return methods.interfaces.get(INTERFACE_BANK);
    }

    /**
     * Gets the deposit box interface.
     *
     * @return The deposit box <code>RSInterface</code>.
     */
    public RSInterface getBoxInterface() {
        return methods.interfaces.get(INTERFACE_BANK);
    }

    /**
     * Gets the <code>RSComponent</code> of the given item at the specified index.
     *
     * @param index The index of the item.
     * @return <code>RSComponent</code> if item is found at index; otherwise null.
     */
    public RSItem getItemAt(final int index) {
        final RSItem[] items = getItems();
        if (items != null) {
            for (final RSItem item : items) {
                if (item.getComponent().getComponentIndex() == index) {
                    return item;
                }
            }
        }
        return null;
    }

    /**
     * Gets the first item with the provided ID/Name in the bank.
     *
     * @param item ID/Name of the item to get.
     * @return The component of the item; otherwise null.
     */
    public RSItem getItem(final Object item) {
        final RSItem[] Items = methods.bank.getItems();
        if (Items != null) {
            for (final RSItem Item : Items) {
                if (item instanceof Integer) {
                    if (Item.getID() == (Integer) item) {
                        return Item;
                    }
                }
                if (item instanceof String) {
                    if (Item.getName().equalsIgnoreCase(item.toString())) {
                        return Item;
                    }
                }
            }
        }
        return null;
    }

    /**
     * Gets the point on the screen for a given item. Numbered left to right then top to bottom.
     *
     * @param slot The index of the item.
     * @return The point of the item or new Point(-1, -1) if null.
     */
    public Point getItemPoint(final int slot) {
        if (slot < 0) {
            throw new IllegalArgumentException("slot < 0 " + slot);
        }
        final RSItem item = getItemAt(slot);
        if (item != null) {
            return item.getComponent().getLocation();
        }
        return new Point(-1, -1);
    }

    /**
     * Gets all the items in the bank's inventory.
     *
     * @return an <code>RSItem</code> array of the bank's inventory interface.
     */
    public RSItem[] getItems() {
        if (getInterface() == null || getInterface().getComponent(INTERFACE_BANK_INVENTORY) == null) {
            return new RSItem[0];
        }
        final RSComponent[] components = getInterface().getComponent(INTERFACE_BANK_INVENTORY).getComponents();
        final RSItem[] items = new RSItem[components.length];
        for (int i = 0; i < items.length; ++i) {
            items[i] = new RSItem(methods, components[i]);
        }
        return items;
    }

    /**
     * Checks whether or not the bank is open.
     *
     * @return <tt>true</tt> if the bank interface is open; otherwise <tt>false</tt>.
     */
    public boolean isOpen() {
        return getInterface().isValid();
    }

    /**
     * Checks whether or not the deposit box is open.
     *
     * @return <tt>true</tt> if the deposit box interface is open; otherwise <tt>false</tt>.
     */
    public boolean isDepositOpen() {
        return methods.interfaces.get(INTERFACE_DEPOSIT_BOX).isValid();
    }

    /**
     * Opens one of the supported banker NPCs, booths, or chests nearby. If they
     * are not nearby, and they are not null, it will automatically walk to the
     * closest one.
     *
     * @return <tt>true</tt> if the bank was opened; otherwise <tt>false</tt>.
     */
    public boolean open() {
        if (isOpen()) {
            return true;
        }
        try {
            if (methods.menu.isOpen()) {
                methods.mouse.moveRandomly(450);
                sleep(random(40, 80));
            }
            Object[] banks = {methods.objects.getNearest(Bank.BANK_CHESTS), methods.objects.getNearest(Bank.BANK_BOOTHS), methods.npcs.getNearest(Bank.BANKERS)};
            int[] dis = {methods.calc.distanceTo((RSObject) banks[0]), methods.calc.distanceTo((RSObject) banks[1]), methods.calc.distanceTo((RSNPC) banks[2])};
            String[][] actions = {{"Open", "Use", "Bank"}, {"Use-quickly"}, {"Bank"}};
            RSObject object = (RSObject) banks[1];
            RSNPC npc = (RSNPC) banks[2];
            String[] action = npc != null ? actions[2] : object != null ? actions[1] : null;
            /** find closest */
            if (object != null && npc != null) {
                if (dis[1] < dis[2]) {
                    object = (RSObject) banks[1];
                    action = actions[1];
                    npc = null;
                } else {
                    npc = (RSNPC) banks[2];
                    action = actions[2];
                    object = null;
                }
            }
            if (object == null && npc == null) {
                object = (RSObject) banks[0];
                action = actions[0];
            }
            RSTile tile = object == null ? npc == null ? null : npc.getLocation() : object.getLocation();
            String finalAction = null;
            boolean didAction = false;
            if (object != null && methods.calc.distanceTo(object) < 5) {
                methods.mouse.move(object.getPoint());
                RSObjectDef def = object.getDef();
                if (def != null) {
                    outer:
                    for (String s : action) {
                        for (String i : def.getActions()) { // find correct action; instead of trying all.
                            if (i != null && i.contains(s)) {
                                finalAction = s;
                                break outer;
                            }
                        }
                    }
                    didAction = finalAction != null && object.interact(finalAction + " " + object.getName());
                } else {
                    for (int i = 0; i < action.length && !didAction; i++) {
                        didAction = object.interact(action[i] + " " + object.getName());
                    }
                }
            } else if (npc != null && methods.calc.distanceTo(npc.getLocation()) < 5) {
                methods.mouse.move(npc.getPoint());
                outer:
                for (String s : action) {
                    for (String i : npc.getActions()) {
                        if (i != null && i.contains(s)) { // finding correct action
                            finalAction = s;
                            break outer;
                        }
                    }
                }
                didAction = npc.interact(finalAction + " " + npc.getName());
            } else if (tile != null) {
                methods.walking.walkTileMM(tile);
            }
            if (didAction) {
                int count = 0;
                while (!isOpen() && ++count < 10) {
                    sleep(random(100, 200));
                    if (methods.players.getMyPlayer().isMoving()) {
                        count = 0;
                    }
                }
            }
            return isOpen();
        } catch (final Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * Opens one of the supported deposit boxes nearby. If they are not nearby, and they are not null,
     * it will automatically walk to the closest one.
     *
     * @return <tt>true</tt> if the deposit box was opened; otherwise
     *         <tt>false</tt>.
     */
    public boolean openDepositBox() {
        if (isDepositOpen()) {
            return false;
        }
        try {
            if (methods.menu.isOpen()) {
                methods.mouse.moveSlightly();
                sleep(random(20, 30));
            }
            final RSObject depositBox = methods.objects.getNearest(DEPOSIT_BOXES);
            if (depositBox == null) {
                return false;
            }
            if (methods.calc.distanceTo(depositBox) < 5 && methods.calc.tileOnMap(depositBox.getLocation()) && methods.calc.canReach(depositBox.getLocation(), true)) {
                if (depositBox.interact("Deposit")) {
                    int count = 0;
                    while (!isDepositOpen() && ++count < 10) {
                        sleep(random(200, 400));
                        if (methods.players.getMyPlayer().isMoving()) {
                            count = 0;
                        }
                    }
                } else {
                    methods.camera.turnTo(depositBox, 20);
                }
            } else {
                if (!methods.walking.walkTo(depositBox.getLocation())) {
                    methods.walking.walkTileMM(depositBox.getLocation());
                }
            }
            return isDepositOpen();
        } catch (final Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * Opens the bank tab.
     *
     * @param tabNumber The tab number - e.g. view all is 1.
     * @return <tt>true</tt> on success.
     */
    public boolean openTab(final int tabNumber) {
        return isOpen() && methods.interfaces.getComponent(INTERFACE_BANK, INTERFACE_BANK_TAB[tabNumber - 1]).doClick();
    }

    /**
     * @return <tt>true</tt> if currently searching the bank.
     */
    public boolean isSearchOpen() {
        // Setting 1248 is -2147483648 when search is enabled and -2013265920
        return methods.settings.getSetting(1248) == -2147483648;
    }

    /**
     * Searches for an item in the bank. Returns true if succeeded (does not
     * necessarily mean it was found).
     *
     * @param itemName The item name to find.
     * @return <tt>true</tt> on success.
     */
    public boolean searchItem(final String itemName) {
        if (!isOpen()) {
            return false;
        }
        methods.interfaces.getComponent(INTERFACE_BANK, INTERFACE_BANK_BUTTON_SEARCH).interact("Search");
        sleep(random(1000, 1500));
        if (!isSearchOpen()) {
            sleep(500);
        }
        if (isOpen() && isSearchOpen()) {
            methods.inputManager.sendKeys(itemName, false);
            sleep(random(300, 700));
            return true;
        }
        return false;
    }

    /**
     * Sets the bank rearrange mode to insert.
     *
     * @return <tt>true</tt> on success.
     */
    public boolean setRearrangeModeToInsert() {
        if (!isOpen()) {
            return false;
        }
        if (methods.settings.getSetting(Settings.SETTING_BANK_TOGGLE_REARRANGE_MODE) != 1) {
            methods.interfaces.getComponent(INTERFACE_BANK, INTERFACE_BANK_BUTTON_INSERT).doClick();
            sleep(random(500, 700));
        }
        return methods.settings.getSetting(Settings.SETTING_BANK_TOGGLE_REARRANGE_MODE) == 1;
    }

    /**
     * Sets the bank rearrange mode to swap.
     *
     * @return <tt>true</tt> on success.
     */
    public boolean setRearrangeModeToSwap() {
        if (!isOpen()) {
            return false;
        }
        if (methods.settings.getSetting(Settings.SETTING_BANK_TOGGLE_REARRANGE_MODE) != 0) {
            methods.interfaces.getComponent(INTERFACE_BANK, INTERFACE_BANK_BUTTON_SWAP).doClick();
            sleep(random(500, 700));
        }
        return methods.settings.getSetting(Settings.SETTING_BANK_TOGGLE_REARRANGE_MODE) == 0;
    }

    /**
     * Sets the bank withdraw mode to item.
     *
     * @return <tt>true</tt> on success.
     */
    public boolean setWithdrawModeToItem() {
        if (!isOpen()) {
            return false;
        }
        if (methods.settings.getSetting(Settings.SETTING_BANK_TOGGLE_WITHDRAW_MODE) != 0) {
            methods.interfaces.getComponent(INTERFACE_BANK, INTERFACE_BANK_BUTTON_ITEM).doClick();
            sleep(random(500, 700));
        }
        return methods.settings.getSetting(Settings.SETTING_BANK_TOGGLE_WITHDRAW_MODE) == 0;
    }

    /**
     * Sets the bank withdraw mode to note.
     *
     * @return <tt>true</tt> on success.
     */
    public boolean setWithdrawModeToNote() {
        if (!isOpen()) {
            return false;
        }
        if (methods.settings.getSetting(Settings.SETTING_BANK_TOGGLE_WITHDRAW_MODE) != 1) {
            methods.interfaces.getComponent(INTERFACE_BANK, INTERFACE_BANK_BUTTON_NOTE).doClick();
            sleep(random(500, 700));
        }
        return methods.settings.getSetting(Settings.SETTING_BANK_TOGGLE_WITHDRAW_MODE) == 1;
    }

    /**
     * Tries to withdraw an item.
     * 0 is All. -1 is All but one, 1, 5, 10 use Withdraw 1, 5, 10 while other numbers Withdraw X.
     *
     * @param itemID The ID of the item.
     * @param count  The number to withdraw.
     * @return <tt>true</tt> on success.
     */
    public boolean withdraw(final int itemID, final int count) {
        if (!isOpen()) {
            return false;
        }
        if (count < -1) {
            throw new IllegalArgumentException("count (" + count + ") < -1");
        }
        final RSItem rsi = getItem(itemID);
        if (rsi == null || rsi.getID() == -1) {
            return false;
        }
        final RSComponent item = rsi.getComponent();
        if (item == null) {
            return false;
        }
        int t = 0;
        while (item.getRelativeX() == 0 && getCurrentTab() != 0 && t < 5) {
            if (methods.interfaces.getComponent(Bank.INTERFACE_BANK, Bank.INTERFACE_BANK_TAB[0]).doClick()) {
                sleep(random(800, 1300));
            }
            t++;
        }
        if (!methods.interfaces.scrollTo(item, (Bank.INTERFACE_BANK << 16) + Bank.INTERFACE_BANK_SCROLLBAR)) {
            return false;
        }
        final int invCount = methods.inventory.getCount(true);
        item.doClick(count == 1);
        final String defaultAction = "Withdraw-" + count;
        String action = null;
        switch (count) {
            case 0:
                action = "Withdraw-All";
                break;
            case -1:
                action = "Withdraw-All but one";
                break;
            case 1:
                break;
            case 5:
                action = defaultAction;
                break;
            case 10:
                action = defaultAction;
                break;
            default:
                int i = -1;
                try {
                    i = Integer.parseInt(item.getActions()[3].toLowerCase().trim().replaceAll("\\D", ""));
                } catch (final Exception e) {
                    e.printStackTrace();
                }
                if (i == count) {
                    action = defaultAction;
                } else if (item.interact("Withdraw-X")) {
                    sleep(random(1000, 1300));
                    methods.keyboard.sendText(String.valueOf(count), true);
                }
        }
        if (action != null && item.interact(action)) {
            sleep(random(1000, 1300));
        }
        final int newInvCount = methods.inventory.getCount(true);
        return newInvCount > invCount;
    }

    /**
     * Tries to withdraw an item.
     * 0 is All. -1 is All but one, 1, 5, 10 use Withdraw 1, 5, 10 while other numbers Withdraw X.
     *
     * @param itemName The Name of the item.
     * @param count    The number to withdraw.
     * @return <tt>true</tt> on success.
     */
    public boolean withdraw(final String itemName, final int count) {
        return withdraw(getItem(itemName).getID(), count);
    }

    /**
     * Gets the count of all the items in the inventory with the any of the
     * specified IDs while deposit box is open.
     *
     * @param ids the item IDs to include
     * @return The count.
     */
    public int getBoxCount(final int... ids) {
        if (!isDepositOpen()) {
            return -1;
        }
        int count = 0;
        for (int i = 0; i < 28; ++i) {
            for (final int id : ids) {
                if (methods.interfaces.get(11).getComponent(17).isValid() && methods.interfaces.get(11).getComponent(17).getComponent(i).getComponentID() == id) {
                    count++;
                }
            }
        }
        return count;
    }

    /**
     * Gets the count of all items in your inventory ignoring stack sizes while
     * deposit box is open.
     *
     * @return The count.
     */
    public int getBoxCount() {
        if (!isDepositOpen()) {
            return -1;
        }
        int count = 0;
        for (int i = 0; i < 28; i++) {
            if (methods.interfaces.get(11).getComponent(17).isValid() && methods.interfaces.get(11).getComponent(17).getComponent(i).getComponentID() != -1) {
                count++;
            }
        }
        return count;
    }

    /**
     * Gets the equipment items from the bank interface.
     *
     * @return All equipment items that are being worn.
     */
    public RSItem[] getEquipmentItems() {
        if (methods.interfaces.get(INTERFACE_EQUIPMENT).getComponent(INTERFACE_EQUIPMENT_COMPONENT).isValid()) {
            return new RSItem[0];
        }
        final RSComponent[] components = methods.interfaces.get(INTERFACE_EQUIPMENT).getComponent(INTERFACE_EQUIPMENT_COMPONENT).getComponents();
        final RSItem[] items = new RSItem[components.length];
        for (int i = 0; i < items.length; i++) {
            items[i] = new RSItem(methods, components[i]);
        }
        return items;
    }

    /**
     * Gets a equipment item from the bank interface.
     *
     * @param id ID of the item.
     * @return RSItem
     */
    public RSItem getEquipmentItem(final int id) {
        final RSItem[] items = getEquipmentItems();
        if (items != null) {
            for (final RSItem item : items) {
                if (item.getID() == id) {
                    return item;
                }
            }
        }
        return null;
    }

    /**
     * Gets the ID of a equipment item based on name.
     *
     * @param name Name of the item.
     * @return -1 if item is not found.
     */
    public int getEquipmentItemID(final String name) {
        final RSItem[] items = getEquipmentItems();
        if (items != null) {
            for (final RSItem item : items) {
                if (item.getName().contains(name)) {
                    return item.getID();
                }
            }
        }
        return -1;
    }

    /**
     * Opens the equipment interface.
     *
     * @return <tt>true</tt> if opened.
     */
    public boolean openEquipment() {
        return getInterface().getComponent(INTERFACE_BANK_BUTTON_OPEN_EQUIP).isValid() && getInterface().getComponent(INTERFACE_BANK_BUTTON_OPEN_EQUIP).doClick();
    }

    /**
     * Gets the item ID of a item side the bank.
     *
     * @param name Name of the item.
     * @return -1 if item is not found.
     */
    public int getItemID(final String name) {
        final RSItem[] items = getItems();
        if (items != null) {
            for (final RSItem item : items) {
                if (item.getName().toLowerCase().equals(name.toLowerCase())) {
                    return item.getID();
                }
            }
            for (final RSItem item : items) {
                if (item.getName().toLowerCase().contains(name.toLowerCase())) {
                    return item.getID();
                }
            }
        }
        return -1;
    }
}